package main

import (
	"fmt"
	"math"
	"strconv"
	"image"
)

//以此类型为基础添加方法
type Vertex struct {
	X, Y float64
}
type MyFloat float64

//接口，类似于纯虚函数
type Abser interface {
	Abs() float64
}

//方法，实现了接口
func (v *Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

//实现fmt中的Stringer，这样可以fmt.Println(v)
func (v *Vertex) String() string {
	return fmt.Sprintf("X=%v Y=%v", v.X, v.Y)
}


func Run4() {
	fmt.Println("Run4 --------------------------------")

	//Go 没有类。
	//然而，仍然可以在结构体类型上定义方法。
	v := &Vertex{3, 4}
	fmt.Println("v.Abs =", v.Abs())
	
	//你可以对包中的 任意 类型定义任意方法，而不仅仅是针对结构体。
	f := MyFloat(3.1415927)
	fmt.Println("f.Abs =", f.Abs())

	//接口
	var a Abser
	a = v //a *Vertex 实现了 Abser
	fmt.Println("a.Abs =", a.Abs())
	a = f //a MyFloat 实现了 Abser
	fmt.Println("a.Abs =", a.Abs())

	//隐式接口（鸭子）
	//这里的 *Vertex 和 MyFloat 都是Abser

	//Stringers “fmt”包中定义的 Stringer 的接口。
	fmt.Println(v);

	// error 错误
	//通常函数会返回一个 error 值，为 nil 时表示成功。
	i, err := strconv.Atoi("abc")
	if err != nil {
		fmt.Printf("couldn't convert number: %v\n", err)
	} else {
		fmt.Println("Converted integer:", i)
	}

	// image 图片
	m := image.NewRGBA(image.Rect(0, 0, 100, 100))
	fmt.Println(m.Bounds())
	fmt.Println(m.At(0, 0).RGBA())
}


